﻿using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Autofac;

namespace Sail
{
    /// <summary>
    /// 站点运行上下文扩展类
    /// </summary>
    public static class WorkContextExtensions
    {
        /// <summary>
        /// 获取站点运行上下文对象
        /// </summary>
        /// <param name="workContextAccessor">站点运行上下文访问对象</param>
        /// <param name="controllerContext">控制器上下文对象</param>
        /// <returns>站点运行上下文</returns>
        public static WorkContext GetContext(this IWorkContextAccessor workContextAccessor, ControllerContext controllerContext)
        {
            return workContextAccessor.GetContext(controllerContext.RequestContext.HttpContext);
        }

        /// <summary>
        /// 获取站点运行上下文对象
        /// </summary>
        /// <param name="requestContext">请求上下文对象</param>
        /// <returns>站点运行上下文对象</returns>
        public static WorkContext GetWorkContext(this RequestContext requestContext)
        {
            if (requestContext == null)
                return null;

            var routeData = requestContext.RouteData;
            if (routeData == null || routeData.DataTokens == null)
                return null;

            object workContextValue;
            if (!routeData.DataTokens.TryGetValue("IWorkContextAccessor", out workContextValue))
            {
                workContextValue = FindWorkContextInParent(routeData);
            }

            if (!(workContextValue is IWorkContextAccessor))
                return null;

            var workContextAccessor = (IWorkContextAccessor)workContextValue;
            return workContextAccessor.GetContext(requestContext.HttpContext);
        }

        /// <summary>
        /// 获取站点运行上下文对象
        /// </summary>
        /// <param name="controllerContext">控制器上下文对象</param>
        /// <returns>站点运行上下文对象</returns>
        public static WorkContext GetWorkContext(this ControllerContext controllerContext)
        {
            if (controllerContext == null)
                return null;

            return GetWorkContext(controllerContext.RequestContext);
        }

        /// <summary>
        /// 获取站点运行上下文对象作用域
        /// </summary>
        /// <param name="lifetimeScope"></param>
        /// <param name="httpContext">httpContext对象</param>
        /// <returns>站点运行上下文对象作用域</returns>
        public static IWorkContextScope CreateWorkContextScope(this ILifetimeScope lifetimeScope, HttpContextBase httpContext)
        {
            return lifetimeScope.Resolve<IWorkContextAccessor>().CreateWorkContextScope(httpContext);
        }

        /// <summary>
        /// 获取站点运行上下文对象作用域
        /// </summary>
        /// <param name="lifetimeScope"></param>
        /// <returns>站点运行上下文对象作用域</returns>
        public static IWorkContextScope CreateWorkContextScope(this ILifetimeScope lifetimeScope)
        {
            return lifetimeScope.Resolve<IWorkContextAccessor>().CreateWorkContextScope();
        }

        /// <summary>
        /// 查找上下文对象信息
        /// </summary>
        /// <param name="routeData">路由信息对象</param>
        /// <returns>对象</returns>
        private static object FindWorkContextInParent(RouteData routeData)
        {
            object parentViewContextValue;
            if (!routeData.DataTokens.TryGetValue("ParentActionViewContext", out parentViewContextValue)
                || !(parentViewContextValue is ViewContext))
            {
                return null;
            }

            var parentRouteData = ((ViewContext)parentViewContextValue).RouteData;
            if (parentRouteData == null || parentRouteData.DataTokens == null)
                return null;

            object workContextValue;
            if (!parentRouteData.DataTokens.TryGetValue("IWorkContextAccessor", out workContextValue))
            {
                workContextValue = FindWorkContextInParent(parentRouteData);
            }

            return workContextValue;
        }
    }
}